PowerTCP Sockets for .NET
Security Implementation



Client Security

AuthenticateAsClient() is used by client components to perform authentication after connecting to a server. For our Tcp component, this must be called directly, while for our application-layer protocol components, it will be called automatically after the connection is established when SSL is enabled.

When AuthenticateAsClient() is called (either directly, or through top-level methods that will utilize it), two things may occur:

The server presents a certificate:

This will raise the RemoteCertificateValidationCallback specified by Tcp.Session.Security.ValidationCallback. This callback must be in the format:

C#
Copy Code
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
bool RemoteCertificateValidation(
    Object sender,
    X509Certificate remoteCertificate,
    X509Chain chain,
    SslPolicyErrors sslPolicyErrors)
{
    ...
}
Visual Basic
Copy Code
Imports System.Net.Security
Imports System.Security.Cryptography.X509Certificates
Function RemoteCertificateValidation( _
    ByVal sender As Object, _
    ByVal remoteCertificate As X509Certificate, _
    ByVal chain As X509Chain, _
    ByVal sslPolicyErrors As SslPolicyErrors) As Boolean
    ...
End Function

Return true to accept the certificate, and false to refuse it. A value other than SslPolicyErrors.None for sslPolicyErrors indicates an issue with the certificate that the server presented. A flag of SslPolicyErrors.RemoteCertificateChainErrors indicates that chain.ChainStatus should be checked; enumerate through chain.ChainStatus, and check the value of chain.ChainStatus[index].Status for additional details.

During authentication, the remote certificate's common name (CN) (usually the server's fully qualified domain name) is compared to the value of ClientSecurity.TargetHost. If the values do not match, sslPolicyErrors will contain the SslPolicyErrors.RemoteCertificateNameMismatch flag. When ClientSecurity.TargetHost is left empty, Tcp.Session.RemoteEndPoint.HostNameOrAddress will be used instead.

The server requests a certificate:

AuthenticateAsClient() first checks if Tcp.Session.Security.SelectionCallback is null. If it is not null, that LocalCertificateSelectionCallback will be raised. This callback must be in the format:

C#
Copy Code
using System.Security.Cryptography.X509Certificates;
X509Certificate LocalCertificateSelection(
    Object sender,
    string targetHost,
    X509CertificateCollection localCertificates,
    X509Certificate remoteCertificate,
    string[] acceptableIssuers)
{
    ...
}
Visual Basic
Copy Code
Imports System.Security.Cryptography.X509Certificates
Function LocalCertificateSelection( _
    ByVal sender As Object, _
    ByVal targetHost As String, _
    ByVal localCertificates As X509CertificateCollection, _
    ByVal remoteCertificate As X509Certificate, _
    ByVal acceptableIssuers() As String) As X509Certificate
    ...
End Function

Return a certificate within the callback, and that certificate will be used for authentication. Certificates may be accessed from the certificate store with the System.Security.Cryptography.X509Certificates.X509Store class:

C#
Copy Code
using System.Security.Cryptography.X509Certificates;
//The X509Store constructor overloads may be used to access different certificate stores
X509Store certificateStore = new X509Store();
certificateStore.Open(OpenFlags.ReadOnly);
X509Certificate2 cert = certificateStore.Certificates[0];
Visual Basic
Copy Code
Imports System.Security.Cryptography.X509Certificates
'The X509Store constructor overloads may be used to access different certificate stores
Dim certificateStore As New X509Store()
certificateStore.Open(OpenFlags.ReadOnly)
Dim cert As X509Certificate2 = certificateStore.Certificates(0)

For a demonstration of selecting a certificate from the certificate store interactively, please see the CertificateListForm included with our samples.

If Tcp.Session.Security.SelectionCallback is null, AuthenticateAsClient() will examine Tcp.Session.Security.Certificates for a valid certificate; the first certificate in the collection that passes Microsoft's validation checks will be used for authentication.


Server Security

For our server component, Tcp.AuthenticateAsServer(ServerSecurity) may be called after the client connects. ServerSecurity.ValidationCallback is identical to the client ValidationCallback, and will be raised when the client presents a certificate.

Set the ServerSecurity.Certificate property to specify the certificate to use for authentication.


Security Protocol

The security protocol used will be automatically negotiated; to specify the protocols available for negotiation, Security.Protocols may be set to any combination of the System.Security.Authentication.SslProtocols enumeration.

Dart uses .NET for its encryption implementation, so the availability of protocols and behavior are dependent upon it and the OS. There are SslProtocols availability limitations based upon the project's .NET target and the OS it is executed on; please see the MSDN article Support for SSL/TLS protocols on Windows for information on SslProtocols availability by Windows version, and the target .NET version's System.Security.Authentication.SslProtocols documentation for information on availability by the .NET target.

Under .NET Core 2.0 and .NET Framework 4.7, SslProtocols.None is documented as 'allows the operating system to choose the best protocol to use, and to block protocols that are not secure'. However on Windows 7 SP1 and earlier, SslProtocols.None currently (as of April 2018) results in the availability of only SSL2/SSL3/TLS 1.0; so to use TLS 1.1/1.2 under .NET 4.7/Core 2.0 on Windows 7 SP1 and earlier, they must be specified directly. For more information, please see the Microsoft article Support for TLS System Default Versions included in the .NET Framework 3.5 on Windows 8.1 and Windows Server 2012 R2. Additionally, despite that SslProtocols.None advertises SSL2/SSL3/TLS 1.0 under .NET Core 2.0 and Windows 7 SP1 and earlier, actually specifying SSL2, SSL3 or Default results in a "The requested security protocol is not supported" exception.


Explicit/Implicit

Explicit security means that the initial connection to the server is not encrypted. After connecting, a command such as STARTTLS or STLS is sent by the client to the server per the protocol, and a secure connection is negotiated. Because explicit security is initiated after the STARTTLS command is sent, servers are able to accept explicit connections on the same port that accepts non-secure connections.

Implicit security means that the client and server will negotiate a secure connection when the connection is established. Because of this, a port is typically dedicated for implicit connections.

Explicit/Implicit implementation is protocol-specific; application-layer protocols such as Ftp, Imap, Smtp and Pop implement it, while upper-layer protocols such as Tcp and Udp do not. The method of encryption may be configured on our components with a property on Session.Security. The property's name may vary between components, but will always start with 'Encrypt'; for Ftp, this property is Session.Security.EncryptControl, and for our Email components, Session.Security.Encrypt.


PowerTCP Sockets for .NET Documentation Version 6.1
© 2023 Dart Communications. All Rights Reserved.
Send comments on this topic